//
//  LoginView.swift
//  maosheng
//
//  Created by 何海涛 on 2019/8/10.
//

import Foundation
import UIKit

enum EnumLoginViewMode: UInt {
    case validate = 0
    case password = 1
}

protocol LoginViewDelegate {
    func sendLogin(_ model: ValidationCodeLoginRequest)
    func jumpFindPasswordPage(isRegist : Bool)
    func jumpUserProtocolPage()
    func sendWechatLogin()
}

class LoginView: UIView, UITextFieldDelegate {
    
    var delegate: LoginViewDelegate?
    
    // segment
    lazy var segRegisterAndLogin: YUSegmentedControl = {
        var seg = YUSegmentedControl(titles: ["验证码登录","密码登录"])
        seg.indicator.backgroundColor = VS.mainRed
        seg.isShowsTopSeparator = false
        seg.isShowsBottomSeparator = false
        seg.setTextAttributes([NSAttributedString.Key.foregroundColor:VS.txtMain,
                               NSAttributedString.Key.font:VS.font18.toBold()], for: .selected)
        seg.setTextAttributes([NSAttributedString.Key.foregroundColor:VS.txtSecondary,
                               NSAttributedString.Key.font:VS.font18.toBold()], for: .normal)
        seg.addTarget(self, action: #selector(segmentIndexChanged), for: .valueChanged)
        self.addSubview(seg)
        seg.snp.makeConstraints({ (make) in
            make.left.equalTo(self).offset(40)
            make.right.equalTo(self).offset(-40)
            make.top.equalTo(self).offset(80)
            make.height.equalTo(44)
        })
        return seg
    }()
    
    var currentMode: EnumLoginViewMode {
        return EnumLoginViewMode(rawValue: segRegisterAndLogin.selectedSegmentIndex)
            ?? .validate
    }
    
    // mobile number
    lazy var inputMobile: LoginInputImageView = {
        var input = LoginInputImageView()
        input.withBottomSeparater()
        self.addSubview(input)
        input.snp.makeConstraints({ (make) in
            make.left.equalTo(self).offset(40)
            make.right.equalTo(self).offset(-40)
            make.top.equalTo(segRegisterAndLogin.snp.bottom).offset(60)
            make.height.equalTo(44)
        })
        return input
    }()
    
    // validation code
    lazy var inputCode: LoginInputImageView = {
        var input = LoginInputImageView()
        input.withBottomSeparater()
        self.addSubview(input)
        input.snp.makeConstraints({ (make) in
            make.left.equalTo(self).offset(40)
            make.right.equalTo(self).offset(-40)
            make.top.equalTo(self.inputMobile.snp.bottom).offset(20)
            make.height.equalTo(44)
        })
        return input
    }()
    
    // regist pwd
    lazy var btnRegist: UIButton = {
        var btn = UIButton()
        self.addSubview(btn)
        btn.setTitle("立即注册", for: .normal)
        btn.setTitleColor(VS.assistRed, for: .normal)
        btn.titleLabel?.font = VS.font11
        btn.addTarget(self, action: #selector(btnRegistClicked), for: .touchUpInside)
        btn.snp.makeConstraints({ (make) in
            make.left.equalTo(self).offset(40)
            make.top.equalTo(self.inputCode.snp.bottom).offset(10)
        })
        return btn
    }()
    // forget pwd
    lazy var btnForget: UIButton = {
        var btn = UIButton()
        self.addSubview(btn)
        btn.setTitle("忘记密码？", for: .normal)
        btn.setTitleColor(VS.assistRed, for: .normal)
        btn.titleLabel?.font = VS.font11
        btn.addTarget(self, action: #selector(btnForgetClicked), for: .touchUpInside)
        btn.snp.makeConstraints({ (make) in
            make.right.equalTo(self).offset(-40)
            make.top.equalTo(self.inputCode.snp.bottom).offset(10)
        })
        return btn
    }()
    
    // login
    lazy var btnLogin: UIButton = {
        var btn = UIButton()
        btn.setMutexColor(colorPairs: MutexColors.Disable)
        btn.setTitle("登陆", for: .normal)
        btn.setCorner(22)
        btn.titleLabel?.font = VS.font18
        btn.addTarget(self, action: #selector(btnLoginClicked), for: .touchUpInside)
        self.addSubview(btn)
        btn.snp.makeConstraints({ (make) in
            make.top.equalTo(inputCode.snp.bottom).offset(50)
            make.left.equalTo(self).offset(40)
            make.right.equalTo(self).offset(-40)
            make.height.equalTo(44)
        })
        return btn
    }()
    
    fileprivate lazy var agreementContainer: UIView = {
        // container to keep btnAgreement + btnProtocol center of view.
        var view = UIView()
        self.addSubview(view)
        view.snp.makeConstraints({ (make) in
            make.centerX.equalTo(self)
            make.top.equalTo(self.btnLogin.snp.bottom).offset(40)
        })
        return view
    }()
    
    lazy var btnAgreement: UIButton = {
        var btn = UIButton()
        btn.setTitle(" 我已阅读同意遵守", for: .normal)
        btn.setTitleColor(VS.txtSubhead, for: .normal)
        btn.setImage(UIImage(named: "common_checked"), for: .selected)
        btn.setImage(UIImage(named: "common_unchecked"), for: .normal)
        btn.titleLabel?.font = VS.font10
        btn.addTarget(self, action: #selector(btnAgreementClicked), for: .touchUpInside)
        self.agreementContainer.addSubview(btn)
        btn.snp.makeConstraints({ (make) in
            make.left.top.bottom.equalToSuperview()
        })
        return btn
    }()
    
    lazy var btnUserProtocol: UIButton = {
        var btn = UIButton()
        btn.setTitle("《用户注册协议》", for: .normal)
        btn.setTitleColor(VS.assistRed, for: .normal)
        btn.titleLabel?.font = VS.font10
        btn.addTarget(self, action: #selector(btnUserProtocolClicked), for: .touchUpInside)
        self.agreementContainer.addSubview(btn)
        btn.snp.makeConstraints({ (make) in
            make.right.equalToSuperview()
            make.left.equalTo(self.btnAgreement.snp.right)
            make.centerY.equalTo(self.btnAgreement)
        })
        return btn
    }()
    
    // other login way
    fileprivate lazy var lblWx: UILabel = {
        var lbl = VS.makeLabel(VS.font12, VS.txtSubhead)
        lbl.text = "微信登陆"
        self.addSubview(lbl)
        lbl.snp.makeConstraints({ (make) in
            make.centerX.equalToSuperview()
            make.bottom.equalTo(self).offset(-120)
        })
        return lbl
    }()
    
    fileprivate lazy var sepWxLeft: UIView = {
        var sep = VS.makeSeparator()
        sep.backgroundColor = VS.txtSubhead
        self.addSubview(sep)
        sep.snp.makeConstraints({ (make) in
            make.centerY.equalTo(self.lblWx)
            make.left.equalTo(self).offset(40)
            make.right.equalTo(self.lblWx.snp.left).offset(-20)
            make.height.equalTo(1.5)
        })
        return sep;
    }()
    
    fileprivate lazy var sepWxRight : UIView = {
        var sep = VS.makeSeparator()
        sep.backgroundColor = VS.txtSubhead
        self.addSubview(sep)
        sep.snp.makeConstraints({ (make) in
            make.centerY.equalTo(self.lblWx)
            make.left.equalTo(self.lblWx.snp.right).offset(20)
            make.right.equalTo(self).offset(-40)
            make.height.equalTo(1.5)
        })
        return sep;
    }()
    
    lazy var btnWx: UIButton = {
        var btn = UIButton()
        btn.setImage(UIImage(named: "common_wechat"), for: .normal)
        btn.addTarget(self, action: #selector(btnWechatClicked), for: .touchUpInside)
        self.addSubview(btn)
        btn.snp.makeConstraints({ (make) in
            make.centerX.equalToSuperview()
            make.top.equalTo(self.lblWx.snp.bottom).offset(20)
        })
        return btn
    }()
    
    func render() -> Void {
        // according to current segment set control style.
        inputMobile.render(text: "login_mobile", placeHolder: "请输入手机号", keyboard: .phonePad, showSend: false)
        renderPartialCode(true)
        inputMobile.txt.delegate = self
        inputCode.txt.delegate = self
        inputMobile.txt.addTarget(self, action: #selector(textFieldValueChanged), for: .editingChanged)
        inputCode.txt.addTarget(self, action: #selector(textFieldValueChanged), for: .editingChanged)
        btnUserProtocol.isEnabled = true // trigger lazy variable
        btnWx.isEnabled = true // trigger lazy variable
        sepWxLeft.isHidden = false
        sepWxRight.isHidden = false
    }
    
    @objc
    func segmentIndexChanged() {
        inputCode.txt.text = ""
        renderPartialCode(false)
        _ = validateInput(showError: false)
    }
   
    @objc
    func btnRegistClicked() {
        delegate?.jumpFindPasswordPage(isRegist: true)
    }
    
    @objc
    func btnForgetClicked() {
        delegate?.jumpFindPasswordPage(isRegist: false)
    }
    
    @objc
    func btnLoginClicked() {
        if let model = validateInput(showError: true) {
            delegate?.sendLogin(model)
        }
    }
    
    @objc
    func btnAgreementClicked(){
        btnAgreement.isSelected = !btnAgreement.isSelected
        _ = validateInput(showError: false)
    }
    
    @objc
    func btnUserProtocolClicked() {
        delegate?.jumpUserProtocolPage()
    }
    
    @objc
    func btnWechatClicked() {
        delegate?.sendWechatLogin()
    }
    
    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        _ = validateInput(showError: false)
        return true
    }
    
    func textFieldDidEndEditing(_ textField: UITextField) {
        _ = validateInput(showError: false)
    }
    
    @objc
    func textFieldValueChanged() {
        _ = validateInput(showError: false)
    }
    
    fileprivate func renderPartialCode(_ isInit: Bool){
        let showSend = currentMode == .validate
        let tip = showSend ? "请输入验证码" : "请输入6-20位数字或者字母"
        if isInit {
            inputCode.render(text: "login_password", placeHolder: tip, keyboard: .default, showSend: showSend)
        } else {
            inputCode.txt.placeholder = tip
            inputCode.resetSendBtn(show: showSend)
        }
        inputCode.txt.isSecureTextEntry = !showSend
        btnForget.isHidden = showSend
        btnRegist.isHidden = false

    }
    
    fileprivate func validateInput(showError: Bool) -> ValidationCodeLoginRequest? {
        // model binder
        let model = ValidationCodeLoginRequest()
        let results = ModelBinder.bindModel(model, rules: self, view: self)
        let hasError = results.errors.count > 0
        if showError && hasError { self.handleError(errors: results.errors) }
        
        // login btn style
        self.btnLogin.setMutexColor(colorPairs: hasError ? MutexColors.Disable : MutexColors.RedReverse)
        
        // return
        return hasError ? nil : results.model
    }
}

// validation
extension LoginView: IValidationRuleProvider {
    
    func getValidateRules() -> [ValidationRule] {
        return [
            RequiredValidationRule(memberName: "mobile", displayName: "手机号"),
            RegexValidationRule(memberName: "mobile", pattern: Regex.MobilePattern, errorMessage: "手机号格式有误"),
            self.currentMode == .password
                ? RequiredValidationRule(memberName: "password", displayName: "密码")
                : RequiredValidationRule(memberName: "verifyCode", displayName:"验证码"),
            RegexValidationRule(memberName: "password", pattern: "^[0-9a-zA-Z]{6,20}$", errorMessage: "请输入6-20位数字或者字母"),
            RegexValidationRule(memberName: "agree", pattern: "^1$", errorMessage: "请勾选已阅读同意遵守协议")
        ]
    }
}

extension LoginView: IViewDataBindingProtocol {
    
    func getDataMappings() -> [ViewDataMapping] {
        return [
            ViewDataMapping(memberName: "mobile", valueProvider: { () -> AnyObject? in
                return self.inputMobile.txt.text as AnyObject
            }),
            ViewDataMapping(memberName: self.currentMode == .password ? "password" : "verifyCode", valueProvider: { () -> AnyObject? in
                return self.inputCode.txt.text as AnyObject
            }),
            ViewDataMapping(memberName: "agree", valueProvider: { () -> AnyObject? in
                return (self.btnAgreement.isSelected ? "1" : "0") as AnyObject
            })
        ]
    }
}

extension LoginView: ValidationErrorBehaviorProtocol {
    
    func handleError(errors: [ValidationResult]) {
        if errors.first != nil {
            self.makeToast(errors.first!.errorMessage)
        }
    }
}


